<template>
  <div class="upload-contract" :class="{ 'upload-contract-multiple': limit > 1 }">
    <a-upload
      :action="uploadAction"
      name="files"
      v-model:file-list="uploadValue"
      :limit="limit"
      ref="uploadRef"
      :auto-upload="false"
      :multiple="multiple"
      @before-upload="beforeUpload"
      @change="uploadChange"
    >
      <template #upload-button>
        <a-button type="primary">
          <template #icon>
            <icon-upload />
          </template>
          点击上传
        </a-button>
      </template>
      <template #upload-item="{ fileItem, index }">
        <slot name="upload-item" :fileItem="fileItem" :index="index">
          <div class="arco-upload-list-item" :class="{ 'ml-2': index > 0 }">
            <div class="arco-upload-list-item-content">
              <div class="arco-upload-list-item-name" @click="filePreview(fileItem, index)">
                <div class="arco-upload-list-item-file-icon">
                  <img :src="getFileItemImgSrc(fileItem)" alt="" />
                </div>
                <a-typography-text class="name" :ellipsis="{ showTooltip: true }">
                  {{ fileItem.name }}
                </a-typography-text>
              </div>
            </div>
            <span class="arco-upload-list-item-operation">
              <!-- 进度条 -->
              <div class="progress" v-if="['uploading', 'init'].includes(fileItem.status)">
                {{ fileItem.status == 'init' ? '压缩中' : '上传中' }}
                <!-- 压缩进度条 -->
                <a-progress v-if="fileItem.status == 'init'" size="mini" :percent="fileItem.percent" />
                <!-- 上传进度条 -->
                <a-progress v-if="fileItem.status == 'uploading'" size="mini" :percent="fileItem.percent" />
              </div>
              <span class="arco-icon-hover">
                <a-popconfirm content="是否确认删除？" type="warning" @ok="delItem(index)">
                  <span class="arco-upload-icon arco-upload-icon-remove">
                    <icon-delete />
                  </span>
                </a-popconfirm>
              </span>
            </span>
          </div>
        </slot>
      </template>
    </a-upload>
    <!-- 预览pdf -->
    <pdf-viewer
      :url="pdfViewInfo.url"
      :title="pdfViewInfo.title"
      v-model:visible="pdfViewInfo.show"
      @close="Object.assign(pdfViewInfo, { ...PDFDefaultAttr })"
    />
    <!-- 图片预览组件 -->
    <a-image-preview v-model:visible="previewVisible" :maskClosable="false" :src="previewSrc" />
  </div>
</template>

<script setup lang="ts">
  import { ref, watch, reactive } from 'vue'
  import { getFileInfoList } from '@/api/common/index.js'
  import { Message } from '@arco-design/web-vue'
  import MyCompress from './scripts/upload-compress'
  import pdfIcon from './icons/pdf.png'
  import docIcon from './icons/doc.png'
  import xlsxIcon from './icons/xlsx.png'
  import defaultIcon from './icons/default.png'

  // pdf预览
  import { PDFDefaultAttr } from '@/components/pdf-viewer/const'
  const pdfViewInfo = reactive({ ...PDFDefaultAttr })

  const props = defineProps({
    modelValue: {
      type: [Array, String],
    },
    limit: {
      type: Number,
      default: 1,
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    maxMB: {
      type: Number,
      default: 8,
    },
    // 限制选择文件格式
    accept: {
      type: Array,
      default: () => ['pdf', 'doc', 'docx', 'jpg', 'jpeg', 'png'],
    },
    // single 为true：update:modelValue时，传 fileId
    // single 为false: update:modelValue时，传 [fileId]
    single: {
      type: Boolean,
      default: true,
    },
  })
  const emit = defineEmits(['update:modelValue', 'change'])
  const uploadAction = import.meta.env.VITE_BASE_PATH + '/uploadFile/commonUpload'
  const uploadValue: any = ref([])

  // 初始化 before
  const initValueWatch = watch(
    () => props.modelValue,
    (val) => {
      initValueFn(val)
    }
  )
  const initValueFn = (val: any) => {
    if (val && val.length > 0) {
      // 由于此处需要获取文件名称，需要调用接口
      const idList = props.single ? [val] : val
      getFileInfoList({ idList }).then((res: any) => {
        const result = res.result
        uploadValue.value = result.map((item: any) => {
          return {
            uid: item.fileIdStr,
            name: item.originalFileName,
            status: 'done',
            url: `${import.meta.env.VITE_BASE_PATH}/uploadFile/image/${item.fileIdStr}`,
          }
        })
      })
      // 关闭watch
      initValueWatch && initValueWatch()
    }
  }
  // 首先执行一次防止v-if
  initValueFn(props.modelValue)
  // 初始化 end
  // 缩略图地址
  const getFileItemImgSrc = (fileItem: any) => {
    const fileExt = fileItem.name.split('.').pop().toLowerCase()
    console.log('fileExt', fileExt)
    // 图片预览
    if (['jpg', 'jpeg', 'png'].includes(fileExt)) {
      return fileItem.url
    } else {
      if (['doc', 'docx'].includes(fileExt)) {
        return docIcon
      }
      if (['pdf'].includes(fileExt)) {
        return pdfIcon
      }
      if (['xls', 'xlsx'].includes(fileExt)) {
        return xlsxIcon
      }
      // 默认值
      return defaultIcon
    }
  }
  // 图片预览
  const previewVisible = ref(false)
  const previewSrc = ref('')
  // 文件预览
  const filePreview = (file: any) => {
    let fileName = file.name.split('.').pop().toLowerCase()
    // pdf预览
    // if (fileName == 'pdf') {
    //   Object.assign(pdfViewInfo, {
    //     url: file.url,
    //     title: file.name,
    //     show: true,
    //   })
    //   return
    // }
    // 图片预览
    if (['jpg', 'jpeg', 'png'].includes(fileName)) {
      previewVisible.value = true
      previewSrc.value = file.url
      return
    }

    window.open(file.url)
  }

  // 删除
  const delItem = (index: number) => {
    uploadValue.value.splice(index, 1)
    emitEvent()
  }

  // 上传之前 限制size 限制格式
  const beforeUpload = (file: any) => {
    const fileName = file.name
    // 限制文件格式
    const accept = props.accept
    const lowerCaseAccept = accept.map((item: any) => item.toLowerCase())
    const reg = new RegExp(`\\.(${lowerCaseAccept.join('|')})$`, 'i')
    if (!reg.test(fileName.toLowerCase())) {
      Message.warning(`请上传${accept.join('、')}格式文件`)
      return false
    }
    // 限制文件大小（非图片）
    const isNotImg = /^(?!.*\.(jpg|jpeg|png)$).*$/.test(fileName.toLowerCase())
    if (isNotImg) {
      const fileSize = file.size / 1024 / 1024
      if (fileSize > props.maxMB) {
        Message.error(`文件大小不能大于${props.maxMB}MB`)
        return false
      }
    }
    return true
  }
  // 触发emit事件
  const emitEvent = () => {
    const uploadedList = uploadValue.value.filter((item) => item.status == 'done')
    const ids = uploadedList.map((item: any) => item.uid)
    if (props.single) {
      emit('update:modelValue', ids[0])
      emit('change', ids[0], uploadValue.value[0])
    } else {
      emit('update:modelValue', ids)
      emit('change', ids, uploadValue.value)
    }
  }
  const uploadRef = ref()
  // 修改
  const uploadChange = (fileList: any, fileItem: any) => {
    // 文件初始化
    if (fileItem.status == 'init' && fileItem.percent == 0) {
      // 判断是图片，压缩图片
      if (/\.(jpg|png)$/.test(fileItem.name.toLowerCase())) {
        MyCompress({
          fileItem: fileItem,
          success: (compressedFile: any) => {
            // 更新文件，调用 updateFile 方法
            uploadRef.value.updateFile(fileItem.uid, compressedFile)
            // 上传文件，调用 submit 方法
            uploadRef.value.submit(fileItem)
          },
        })
      } else {
        // 上传文件，调用 submit 方法
        uploadRef.value.submit(fileItem)
      }
    } else if (fileItem.status == 'uploading') {
      if (fileItem.percent > 0.99) fileItem.percent = 0.99
    } else if (fileItem.status == 'done') {
      uploadValue.value = fileList.map((item: any) => {
        if (item.response) {
          item.uid = item.response.result[0].fileIdStr
          // 图片有 url（blod:xxx）重复赋值页面会闪
          if (!item.url) {
            item.url = `${import.meta.env.VITE_BASE_PATH}/uploadFile/image/${item.uid}`
          }
        }
        return item
      })
      // 判断是否全部上传完毕，不存在初始化(压缩中)及上传中的文件
      const hasUploading = uploadValue.value.some((item: any) => ['init', 'uploading'].includes(item.status))
      if (!hasUploading) {
        emitEvent()
      }

      // 关闭watch
      initValueWatch && initValueWatch()
    }
  }
  defineExpose({
    /**
     * @param ids 更新文件id，可能为单个id，也可能是数组
     */
    update: (ids: any) => {
      emit('update:modelValue', ids)
      if (ids) {
        initValueFn(ids)
      } else {
        uploadValue.value = []
      }
    },
  })
</script>
<style lang="less" scoped>
  .upload-contract {
    .arco-upload-list-item {
      height: 73px;
      padding: 8px 12px;
      background: #f7f8fa;
    }
    .arco-upload-list-item-content {
      background: #f7f8fa;
      padding: 0;
      max-height: 100%;
    }
    .arco-upload-list-item-name {
      margin-right: 0;
    }
    .arco-upload-list-item-file-icon {
      width: 40px;
      flex-shrink: 0;
      img {
        width: 40px;
      }
    }
    .arco-upload-list-item-operation {
      display: flex;
      align-items: center;
      .progress {
        max-width: 58px;
        margin-right: 10px;
      }
    }
    .name {
      margin-bottom: 0;
      width: 160px;
      cursor: pointer;
    }
  }
  .arco-upload-list-item-done .arco-upload-list-item-file-icon {
    color: rgb(var(--primary-6));
  }
  .upload-contract {
    display: inline-block;
    width: 100%;
  }
  .upload-contract-multiple {
    :deep(.arco-upload-list) {
      display: flex;
      justify-content: flex-start;
      align-items: flex-end;
      flex-wrap: wrap;
    }
  }
</style>
